﻿//efficiency.cpp
#include "../Inc/efficiency.h"
#include <shlwapi.h>
#include <assert.h>

namespace sbase
{
	//////////////////////////////////////////////////////////////////////////

	CEfficiency::CEfficiency()
	{
		QueryPerformanceFrequency(&m_CpuFreq);
		m_fp = NULL;
		m_nID = 0;

	}

	CEfficiency::~CEfficiency()
	{
		m_RecordMap.clear();
		if(m_fp)
			fclose(m_fp);
	}

	void CEfficiency::update()
	{
		for (RecordMap::iterator it = m_RecordMap.begin(); it != m_RecordMap.end(); ++it) {
			SRecordNode* node = &it->second;
			node->m_TotelCount += node->m_FrameCount;
			node->m_TotelTime.QuadPart += node->m_FrameTime.QuadPart;
			node->m_FrameCount = 0;
			node->m_FrameTime.QuadPart = 0;
		}
	}

	void CEfficiency::beginRecord(const char* Name)
	{
		if (!Name)
			return;

		SRecordNode* node = 0;
		RecordMap::iterator it = m_RecordMap.find(Name);
		if (it == m_RecordMap.end())
		{
			SRecordNode node = {0};
			m_RecordMap.insert(stdext::hash_map<std::string,SRecordNode>::value_type(Name, node));
		}

		it = m_RecordMap.find(Name);
		node = &it->second;
		if(node)
		{
			QueryPerformanceCounter(&node->m_BeginTimeMs);
			node->m_FrameCount ++;
		}
	}

	void CEfficiency::endRecord(const char* Name)
	{
		if (!Name)
			return;

		SRecordNode* node = 0;
		RecordMap::iterator it = m_RecordMap.find(Name);
		if (it != m_RecordMap.end())
			node = &it->second;
		if(node)
		{
			QueryPerformanceCounter(&node->m_EndTimeMs);
			node->m_FrameTime.QuadPart = (node->m_EndTimeMs.QuadPart - node->m_BeginTimeMs.QuadPart);
		}
	}

	HANDLE CEfficiency::GetRecord(const char* Name)
	{
		if (Name)
		{
			RecordMap::iterator it = m_RecordMap.find(Name);
			if (it == m_RecordMap.end())
			{
				SRecordNode node = {0};
				m_RecordMap.insert(stdext::hash_map<std::string,SRecordNode>::value_type(Name, node));
			}
			
			it = m_RecordMap.find(Name);
			SRecordNode* node = &it->second;
			return (HANDLE)node;
		}
		return NULL;
	}

	void CEfficiency::beginRecordEx(HANDLE hRecord)
	{
		if(hRecord)
		{
			SRecordNode* node = (SRecordNode*)hRecord;
			QueryPerformanceCounter(&node->m_BeginTimeMs);
			node->m_FrameCount ++;
		}
	}
	void CEfficiency::endRecordEx(HANDLE hRecord)
	{
		if(hRecord)
		{
			SRecordNode* node = (SRecordNode*)hRecord;
			QueryPerformanceCounter(&node->m_EndTimeMs);
			node->m_FrameTime.QuadPart += (node->m_EndTimeMs.QuadPart - node->m_BeginTimeMs.QuadPart);
		}
	}



	inline unsigned __int64 GetCpuCount()
	{
		_asm rdtsc;
	}


	void CEfficiency::Dump(bool bCurrentFrame)
	{
		m_nID ++;
		if((m_fp = fopen(m_szFileName, "w+" ))==NULL)
		{
			return;
		}
		fprintf(m_fp,"ID\ttime\ttype\tnode\tnum\tCPUrand\tmsec\n");

		SYSTEMTIME systemTime;
		GetLocalTime(&systemTime);

		for (RecordMap::iterator it = m_RecordMap.begin(); it != m_RecordMap.end(); ++it) 
		{
			SRecordNode* node = &it->second;
			const char * pString = it->first.c_str();

			if(bCurrentFrame)
			{
				if(node->m_FrameCount)
				{
					fprintf(m_fp,"%d\t[%02u:%02u:%02u:%03u]\tFrame\t%s\t%d\t%I64d\t%I64d\n",
						m_nID,
						systemTime.wHour,systemTime.wMinute,systemTime.wSecond,systemTime.wMilliseconds,
						pString,
						node->m_FrameCount,
						node->m_FrameTime,
						node->m_FrameTime.QuadPart * 1000/m_CpuFreq.QuadPart
						);
				}
			}
			else
			{
				if(node->m_TotelCount)
				{
					fprintf(m_fp,"%d\t[%02u:%02u:%02u:%03u]\tTotal\t%s\t%d\t%I64d\t%I64d\n",
						m_nID,
						systemTime.wHour,systemTime.wMinute,systemTime.wSecond,systemTime.wMilliseconds,
						pString,
						node->m_TotelCount,
						node->m_TotelTime,
						node->m_TotelTime.QuadPart * 1000/m_CpuFreq.QuadPart
						);
				}
			}
		}
		fflush(m_fp);
		fclose(m_fp);
	}

	bool CEfficiency::OpenFile(char* lpszFileName)
	{
		// 把文件
		ZeroMemory(m_szFileName,MAX_PATH);
		strncpy_s(m_szFileName,sizeof(m_szFileName),lpszFileName,MAX_PATH);
		PathRenameExtension(m_szFileName,".log");
		return true;
	}

	void CEfficiency::Dump(bool bCurrentFrame, void (*PrintEfficiencyLog)(const char*,...))
	{
		m_nID ++;

		SYSTEMTIME systemTime;
		GetLocalTime(&systemTime);

		PrintEfficiencyLog("-----------------------------------------------------------");
		for (RecordMap::iterator it = m_RecordMap.begin(); it != m_RecordMap.end(); ++it) 
		{
			SRecordNode* node = &it->second;
			const char * pString = it->first.c_str();

			if(bCurrentFrame)
			{
				if(node->m_FrameCount)
				{
					PrintEfficiencyLog("%d\t[%02d:%02d:%02d:%03d]\tFrame\t%s\t%d\t%I64u\t%d\n",
						m_nID,
						systemTime.wHour,systemTime.wMinute,systemTime.wSecond,systemTime.wMilliseconds,
						pString,
						node->m_FrameCount,
						node->m_FrameTime,
						node->m_FrameTime.QuadPart * 1000.0/m_CpuFreq.QuadPart
						);
				}
			}
			else
			{
				if(node->m_TotelCount)
				{
					PrintEfficiencyLog("%d\t[%02d:%02d:%02d:%03d]\tTotal\t%s\t%d\t%I64u\t%d\n",
						m_nID,
						systemTime.wHour,systemTime.wMinute,systemTime.wSecond,systemTime.wMilliseconds,
						pString,
						node->m_TotelCount,
						node->m_TotelTime,
						node->m_TotelTime.QuadPart * 1000.0/m_CpuFreq.QuadPart
						);
				}
			}
		}
	}
}